﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using Speed;

//Carlos 24-fev-2011

namespace SiteTest.WebControls
{

    public delegate void PageNumberChanged(object o, DataPagerEventArgs e);

    [DefaultProperty("Text")]
    [DefaultEvent("PageNumberChanged")]
    [ToolboxData("<{0}:DataPager runat=server></{0}:DataPager>")]
    public class DataPager : WebControl, IPostBackEventHandler
    {

        #region Declarations

        protected ImageButton btnMoveFirst;
        protected ImageButton btnMovePrevious;
        protected ImageButton btnMoveNext;
        protected ImageButton btnMoveLast;
        protected ImageButton btnInfo;
        protected List<LinkButton> btnPages;
        // aqui poderia trocar por um repeater
        LinkButton btnPage1, btnPage2, btnPage3, btnPage4, btnPage5, btnPage6, btnPage7, btnPage8, btnPage9, btnPage10;
        int numLinks = 10;
        List<IButtonControl> allButtons;

        #endregion Declarations

        [Browsable(true)]
        public event PageNumberChanged PageNumberChanged;

        #region Constructors

        public DataPager()
        {
            btnMoveFirst = new ImageButton { Width = Unit.Pixel(20), Height = Unit.Pixel(20), ID = this.ID + "btnMoveFirst" };
            btnMovePrevious = new ImageButton { Width = Unit.Pixel(20), Height = Unit.Pixel(20), ID = this.ID + "btnMoveNext" };
            btnMoveNext = new ImageButton { Width = Unit.Pixel(20), Height = Unit.Pixel(20), ID = this.ID + "btnMovePrevious" };
            btnMoveLast = new ImageButton { Width = Unit.Pixel(20), Height = Unit.Pixel(20), ID = this.ID + "btnMoveLast" };
            btnInfo = new ImageButton { Width = Unit.Pixel(20), Height = Unit.Pixel(20), ID = this.ID + "lblInfo" };

            allButtons = new List<IButtonControl>();

            config(true, btnMoveFirst, btnMovePrevious, btnMoveNext, btnMoveLast, btnInfo);

            btnPages = new List<LinkButton>();
            btnPage1 = CreateButtonPage(1);
            btnPage2 = CreateButtonPage(2);
            btnPage3 = CreateButtonPage(3);
            btnPage4 = CreateButtonPage(4);
            btnPage5 = CreateButtonPage(5);
            btnPage6 = CreateButtonPage(6);
            btnPage7 = CreateButtonPage(7);
            btnPage8 = CreateButtonPage(8);
            btnPage9 = CreateButtonPage(9);
            btnPage10 = CreateButtonPage(10);

            this.Controls.Add(btnMoveFirst);
            this.Controls.Add(btnMovePrevious);
            this.Controls.Add(btnMoveNext);
            this.Controls.Add(btnMoveLast);
            foreach (LinkButton btnPage in btnPages)
                this.Controls.Add(btnPage);
            this.Controls.Add(btnInfo);

            // javascript:__doPostBack(&#39;btnPage2&#39;,&#39;&#39;)
            //btnMoveLast.Attributes.Add("onClientClick", "javascript:__doPostBack('" + btnMoveLast.ClientID + "','')");
            //btnMoveLast.Command += btnMoveLast_Command;
            btnMoveFirst.Click += new ImageClickEventHandler(btnMoveFirtst_Click);
            btnMovePrevious.Click += new ImageClickEventHandler(btnMovePrevious_Click);
            btnMoveNext.Click += new ImageClickEventHandler(btnMoveNext_Click);
            btnMoveLast.Click += new ImageClickEventHandler(btnMoveLast_Click);

            btnMoveFirst.ImageUrl = App.GetUrlIcon("MoveFirst.png");
            btnMovePrevious.ImageUrl = App.GetUrlIcon("MovePrevious.png");
            btnMoveNext.ImageUrl = App.GetUrlIcon("MoveNext.png");
            btnMoveLast.ImageUrl = App.GetUrlIcon("MoveLast.png");
            btnInfo.ImageUrl = App.GetUrlIcon("Info.jpg");

            //CreateChildControls();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (!this.Page.IsPostBack)
            {
            }

            //            ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(), "XXXXX",
            //@"Sys.WebForms.PageRequestManager.getInstance()._origOnFormActiveElement = Sys.WebForms.PageRequestManager.getInstance()._onFormElementActive;
            //Sys.WebForms.PageRequestManager.getInstance()._onFormElementActive = function(element, offsetX, offsetY){
            //    if (element.tagName.toUpperCase() === 'INPUT' && element.type === 'image'){
            //        offsetX = Math.floor(offsetX);
            //        offsetY = Math.floor(offsetY);
            //    }
            //    this._origOnFormActiveElement(element, offsetX, offsetY);
            //};", true);
        }

        LinkButton CreateButtonPage(int index)
        {
            LinkButton btn = new LinkButton();
            btn.Text = index.ToString();
            btn.ID = this.ID + "btnPage" + index;
            btn.Click += new EventHandler(btnPage_Click);
            btnPages.Add(btn);
            config(false, btn);
            return btn;
        }

        #endregion Constructors

        #region Properties

        [Bindable(true)]
        [Category("Pager")]
        [DefaultValue("0")]
        public int TotalItems
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["TotalItems"]);
            }
            set
            {
                ViewState["TotalItems"] = value;
                CalcPages();
            }
        }

        [Bindable(true)]
        [Category("Pager")]
        [DefaultValue("0")]
        public int PageNumber
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["PageNumber"]);
            }
            set
            {
                if (PageNumber != value)
                {
                    ViewState["PageNumber"] = value;
                    if (this.Visible && PageNumber >= 0 && PageNumberChanged != null)
                    {
                        DateTime start = DateTime.Now;
                        PageNumberChanged(this, new DataPagerEventArgs(value, GetFirstItem() - 1, PageNumber * PageSize - 1)); // aqui não pode usar GetLastItem() que não funciona
                        TimeCurrent = DateTime.Now.Subtract(start).TotalSeconds;
                        TimeLonger = Math.Max(TimeLonger, TimeCurrent);
                        // tooltip
                        btnInfo.ToolTip = string.Format(
@"Página atual:
    Número: {0}
    Items: {1} a {2}
    Tempo: {3:0.##} segundo(s)
Total 
    Número de páginas: {4}
    Items:  : {5}
    Itens por página: {6}
    Maior tempo: {7:0.##} segundo(s)
",
 PageNumber, GetFirstItem(), GetLastItem(), TimeCurrent,
 PageCount, TotalItems, PageSize, TimeLonger);

                        CalcPages();
                    }
                }
            }
        }

        [Bindable(false)]
        [Category("Pager")]
        [DefaultValue("0")]
        [Browsable(false)]

        public int FirstPageNumber
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["FirstPageNumber"]);
            }
            set
            {
                ViewState["FirstPageNumber"] = value;
            }
        }

        [Bindable(true)]
        [Category("Pager")]
        [DefaultValue("15")]
        public int PageSize
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["PageSize"]);
            }
            set
            {
                ViewState["PageSize"] = value;
                CalcPages();
            }
        }

        [Bindable(true)]
        [Category("Pager")]
        [Browsable(true)]
        public int PageCount
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["PageCount"]);
            }
            protected set
            {
                ViewState["PageCount"] = value;
                //CalcPages();
            }
        }

        /// <summary>
        /// Registra o tempo de carregamente da página atual
        /// </summary>
        [Bindable(true)]
        [Category("Pager")]
        [Browsable(false)]
        public double TimeCurrent
        {
            get
            {
                EnsureChildControls();
                return Conv.ToDouble(ViewState["TimeCurrent"]);
            }
            protected set
            {
                ViewState["TimeCurrent"] = value;
                //CalcPages();
            }
        }

        /// <summary>
        /// Registra o maior tempo de carregamente de uma página
        /// </summary>
        [Bindable(true)]
        [Category("Pager")]
        [Browsable(false)]
        public double TimeLonger
        {
            get
            {
                EnsureChildControls();
                return Conv.ToInt32(ViewState["TimeLonger"]);
            }
            protected set
            {
                ViewState["TimeLonger"] = value;
                //CalcPages();
            }
        }

        #endregion Properties

        #region Override

        protected override void CreateChildControls()
        {
            //this.Controls.Clear();

            //this.Controls.Add(btnMoveFirst);
            //this.Controls.Add(btnMovePrevious);
            //this.Controls.Add(btnMoveNext);
            //this.Controls.Add(btnMoveLast);
            //foreach (LinkButton btnPage in btnPages)
            //    this.Controls.Add(btnPage);
            //this.Controls.Add(btnInfo);

            base.CreateChildControls();
        }

        protected override void AddAttributesToRender(HtmlTextWriter writer)
        {
            writer.AddAttribute("onClick", Page.ClientScript.GetPostBackEventReference(this, String.Empty));
            base.AddAttributesToRender(writer);
        }

        public override void RenderControl(HtmlTextWriter writer)
        {
            if (this.Visible)
            {

                btnMoveFirst.Enabled = PageNumber > 1 && PageCount > 0;
                btnMovePrevious.Enabled = PageNumber > 1 && PageCount > 0;
                btnMoveNext.Enabled = PageNumber < PageCount && PageCount > 0;
                btnMoveLast.Enabled = PageNumber < PageCount && PageCount > 0;
                btnInfo.Visible = PageNumber > 0 && PageCount > 0;

                btnMoveFirst.ToolTip = btnMoveFirst.Enabled ? getTooltip("Primeira página", 1) : "";
                btnMovePrevious.ToolTip = btnMovePrevious.Enabled ? getTooltip("Página anterior", PageNumber - 1) : "";
                btnMoveNext.ToolTip = btnMoveNext.Enabled ? getTooltip("Próxima página", PageNumber + 1) : "";
                btnMoveLast.ToolTip = btnMoveLast.Enabled ? getTooltip("Última página", PageCount) : "";

                config(true, btnMoveFirst, btnMovePrevious, btnMoveNext, btnMoveLast, btnInfo);

                //foreach (var btn in allButtons)
                //    btn.Style["cursor"] = (btn.Enabled) ? "pointer" : "none";

                writer.RenderBeginTag(HtmlTextWriterTag.Table); // table
                writer.AddStyleAttribute("width", "100%");
                writer.RenderBeginTag(HtmlTextWriterTag.Tr);    // tr

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                btnMoveFirst.RenderControl(writer);
                writer.RenderEndTag();    // td

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                btnMovePrevious.RenderControl(writer);
                writer.RenderEndTag();    // td

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                writer.AddStyleAttribute("align", "center");

                FindFirstPage();
                
                btnPages.ForEach(p => p.Visible = false);

                int index = 0;
                btnPages.ForEach(p => p.Visible = false);
                for (int i = FirstPageNumber; i < FirstPageNumber + Math.Min(PageCount, numLinks); i++)
                {
                    // ViewState["P" + (index + 1)] = index;
                    LinkButton btnPage = btnPages[index];
                    btnPage.CommandArgument = i.ToString();
                    btnPage.Text = i.ToString();
                    // tooltip
                    btnPage.ToolTip = getTooltip("Página", i);
                    btnPage.ForeColor = Color.Blue;
                    btnPage.Font.Underline = true;
                    btnPage.Attributes.Add("style", "margin-left:5px; margin-right:5px");
                    btnPage.Visible = true;
                    Page.ClientScript.GetPostBackClientHyperlink(btnPage, i.ToString());
                    if (i == PageNumber)
                    {
                        btnPage.Enabled = false;
                    }
                    config(false, btnPage);
                    btnPage.RenderControl(writer);
                    index++;
                }

                writer.RenderEndTag();    // td

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                btnMoveNext.RenderControl(writer);
                writer.RenderEndTag();    // td

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                btnMoveLast.RenderControl(writer);
                writer.RenderEndTag();    // td

                writer.RenderBeginTag(HtmlTextWriterTag.Td);
                btnInfo.RenderControl(writer);
                writer.RenderEndTag();    // td

                writer.RenderEndTag();    // tr
                writer.RenderEndTag();    // table

                //this.Page.ClientScript.RegisterForEventValidation("btnMoveLast", "JavaScript");
                Page.ClientScript.RegisterForEventValidation(this.UniqueID);

            }
        }

        void btnPage_Click(object sender, EventArgs e)
        {
            LinkButton btnPage = (LinkButton)sender;
            var page = FirstPageNumber + Convert.ToInt32(btnPage.Text) - 1; 
            PageNumber = page;
        }

        protected override void Render(HtmlTextWriter writer)
        {
            if (DesignMode)
            {
                ChildControlsCreated = false;
                EnsureChildControls();
            }
            RenderContents(writer);
        }

        #endregion Override

        #region Events

        void btnMoveFirtst_Click(object sender, ImageClickEventArgs e)
        {
            MoveFirst();
        }

        void btnMovePrevious_Click(object sender, ImageClickEventArgs e)
        {
            MovePrevious();
        }

        void btnMoveNext_Click(object sender, ImageClickEventArgs e)
        {
            MoveNext();
        }

        void btnMoveLast_Click(object sender, ImageClickEventArgs e)
        {
            MoveLast();
        }

        #endregion Events

        #region Methods

        void CalcPages()
        {
            if (TotalItems == 0)
            {
                PageCount = 0;
            }
            else if (PageSize == 0)
            {
                PageCount = 0;
            }
            else
            {
                PageCount = PageSize > 0 ? Convert.ToInt32(Math.Ceiling(1.0D * TotalItems / PageSize)) : 0;
            }
            FindFirstPage();
        }

        public void MoveFirst()
        {
            CalcPages();
            PageNumber = -1;
            PageNumber = 1;
        }

        public void MovePrevious()
        {
            CalcPages();
            if (PageCount > 0 && PageNumber > 1)
                PageNumber--;
        }

        public void MoveNext()
        {
            CalcPages();
            if (PageCount > 0 && PageNumber < PageCount)
                PageNumber++;
        }

        public void MoveLast()
        {
            PageNumber = -1;
            CalcPages();
            if (PageCount > 0)
                PageNumber = PageCount;
        }

        /// <summary>
        /// Primeiro item da página atual
        /// </summary>
        public int GetFirstItem()
        {
            return GetFirstItem(PageNumber);
        }
        /// <summary>
        /// Primeiro item da página pageNumber
        /// </summary>
        public int GetFirstItem(int pageNumber)
        {
            return (pageNumber - 1) * PageSize + 1;
        }

        /// <summary>
        /// Último item da página atual
        /// </summary>
        public int GetLastItem()
        {
            return GetLastItem(PageNumber);
        }
        /// <summary>
        /// Último item da página pageNumber
        /// </summary>
        public int GetLastItem(int pageNumber)
        {
            return Math.Min(pageNumber * PageSize, TotalItems);
        }

        string getTooltip(string title, int pageNumber)
        {
            return string.Format(
@"{0}: {1}
Itens {2} a {3}",
                title, pageNumber, GetFirstItem(pageNumber), GetLastItem(pageNumber));
        }

        void config(bool setSize, params WebControl[] controls)
        {
            foreach (var control in controls)
            {
                if (setSize)
                {
                    control.Width = Unit.Pixel(20);
                    control.Height = Unit.Pixel(20);
                }
                control.BackColor = Color.Transparent;
                control.ForeColor = Color.Blue;

                // buttons
                var btn = control as IButtonControl;
                if (btn != null)
                {
                    if (!allButtons.Contains(btn))
                        allButtons.Add(btn);
                    if (!control.Enabled)
                        control.ForeColor = Color.Gray;
                }

                //var handler = (IPostBackEventHandler)control;
                //if (handler != null)
                //    Page.RegisterRequiresRaiseEvent(handler);
            }

        }

        /// <summary>
        /// Recarrega a página atual
        /// </summary>
        public void Refresh()
        {
            var pn = PageNumber;
            PageNumber = -1;
            PageNumber = pn;
        }


        void FindFirstPage()
        {
            int p1 = Math.Max(PageNumber - (10 / 2), 1);
            if (p1 + numLinks > PageCount)
                p1 = Math.Max(PageCount - numLinks, 1);

            btnPages.ForEach(p => p.Visible = false);
            FirstPageNumber = p1;
        }
        #endregion Methods


        public void RaisePostBackEvent(string eventArgument)
        {
            ToString();
        }
    }

    public class DataPagerEventArgs : EventArgs
    {

        /// <summary>
        /// Número da página
        /// </summary>
        public int PageNumber;
        /// <summary>
        /// Número do primeiro registro = (PageNumber - 1) * PageSize + 1
        /// </summary>
        public int From;
        /// <summary>
        /// Número do ultimo registro = PageNumber * PageSize + 1
        /// </summary>
        public int To;
        public DataPagerEventArgs(int pageNumber, int from, int to)
        {
            this.PageNumber = pageNumber;
            this.From = from;
            this.To = to;
        }
    }


}
